<html>
<head>
<title>logo_parser.py</title>
</head>

<body>
<h3>logo_parser.py (<a href="logo_parser.py">plain text</a>)</h3>
<hr>
<pre>
<span style="color: darkred">"""The logo_parser module implements a parser for Logo."""

</span><span style="color: blue; font-weight: bold">from </span>buffer <span style="color: blue; font-weight: bold">import </span>Buffer

<span style="color: blue; font-weight: bold">def </span>parse_line<span style="font-weight: bold">(</span>line<span style="font-weight: bold">, </span>chars<span style="font-weight: bold">=</span><span style="color: blue">None</span><span style="font-weight: bold">, </span>depth<span style="font-weight: bold">=</span><span style="color: red">0</span><span style="font-weight: bold">):
    </span><span style="color: darkred">"""Convert a single line of Logo into a list of tokens or lists.

    &gt;&gt;&gt; parse_line('print sum 10 difference 7 3')
    ['print', 'sum', '10', 'difference', '7', '3']
    &gt;&gt;&gt; parse_line('print "this [is a [deep] list]')
    ['print', '"this', ['is', 'a', ['deep'], 'list']]
    """
    </span><span style="color: blue; font-weight: bold">if </span>chars <span style="font-weight: bold">== </span><span style="color: blue">None</span><span style="font-weight: bold">:
        </span>chars <span style="font-weight: bold">= </span>Buffer<span style="font-weight: bold">(</span>line<span style="font-weight: bold">.</span>strip<span style="font-weight: bold">()[:])

    </span>tokens <span style="font-weight: bold">= []
    </span><span style="color: blue; font-weight: bold">while True</span><span style="font-weight: bold">:
        </span><span style="color: blue; font-weight: bold">if </span>chars<span style="font-weight: bold">.</span>current <span style="font-weight: bold">== </span><span style="color: blue">None</span><span style="font-weight: bold">: </span><span style="color: green; font-style: italic"># End of the line
            </span><span style="color: blue; font-weight: bold">if </span>depth <span style="font-weight: bold">!= </span><span style="color: red">0</span><span style="font-weight: bold">:
                </span><span style="color: blue; font-weight: bold">raise </span>SyntaxError<span style="font-weight: bold">(</span><span style="color: red">'Unmatched "[" at ' </span><span style="font-weight: bold">+ </span>str<span style="font-weight: bold">(</span>chars<span style="font-weight: bold">))
            </span><span style="color: blue; font-weight: bold">return </span>tokens
        <span style="color: blue; font-weight: bold">elif </span>chars<span style="font-weight: bold">.</span>current <span style="font-weight: bold">== </span><span style="color: red">' '</span><span style="font-weight: bold">: </span><span style="color: green; font-style: italic"># Skip over spaces
            </span>chars<span style="font-weight: bold">.</span>pop<span style="font-weight: bold">()
        </span><span style="color: blue; font-weight: bold">elif </span>chars<span style="font-weight: bold">.</span>current <span style="font-weight: bold">== </span><span style="color: red">'['</span><span style="font-weight: bold">:
            </span>chars<span style="font-weight: bold">.</span>pop<span style="font-weight: bold">()
            </span>tokens<span style="font-weight: bold">.</span>append<span style="font-weight: bold">(</span>parse_line<span style="font-weight: bold">(</span>line<span style="font-weight: bold">, </span>chars<span style="font-weight: bold">, </span>depth <span style="font-weight: bold">+ </span><span style="color: red">1</span><span style="font-weight: bold">))
        </span><span style="color: blue; font-weight: bold">elif </span>chars<span style="font-weight: bold">.</span>current <span style="font-weight: bold">== </span><span style="color: red">']'</span><span style="font-weight: bold">:
            </span><span style="color: blue; font-weight: bold">if </span>depth <span style="font-weight: bold">== </span><span style="color: red">0</span><span style="font-weight: bold">:
                </span><span style="color: blue; font-weight: bold">raise </span>SyntaxError<span style="font-weight: bold">(</span><span style="color: red">'Unexpected "]" at ' </span><span style="font-weight: bold">+ </span>str<span style="font-weight: bold">(</span>chars<span style="font-weight: bold">))
            </span><span style="color: blue; font-weight: bold">else</span><span style="font-weight: bold">:
                </span>chars<span style="font-weight: bold">.</span>pop<span style="font-weight: bold">()
                </span><span style="color: blue; font-weight: bold">return </span>tokens
        <span style="color: blue; font-weight: bold">else</span><span style="font-weight: bold">:
            </span>tokens<span style="font-weight: bold">.</span>append<span style="font-weight: bold">(</span>parse_token<span style="font-weight: bold">(</span>chars<span style="font-weight: bold">))

</span>LOGO_OPERATORS <span style="font-weight: bold">= </span>set<span style="font-weight: bold">(</span><span style="color: red">'+-*/=&lt;&gt;()'</span><span style="font-weight: bold">[:])
</span>LOGO_DELIMITERS <span style="font-weight: bold">= </span>set<span style="font-weight: bold">(</span><span style="color: red">'[]\n '</span><span style="font-weight: bold">[:]).</span>union<span style="font-weight: bold">(</span>LOGO_OPERATORS<span style="font-weight: bold">)

</span><span style="color: blue; font-weight: bold">def </span>parse_symbol<span style="font-weight: bold">(</span>chars<span style="font-weight: bold">):
    </span><span style="color: darkred">"""Parse the next symbol from a buffer chars, starting at chars.current."""
    </span>symbol <span style="font-weight: bold">= </span>chars<span style="font-weight: bold">.</span>pop<span style="font-weight: bold">()
    </span><span style="color: blue; font-weight: bold">while </span>chars<span style="font-weight: bold">.</span>current <span style="color: blue; font-weight: bold">is not </span><span style="color: blue">None </span><span style="color: blue; font-weight: bold">and </span>chars<span style="font-weight: bold">.</span>current <span style="color: blue; font-weight: bold">not in </span>LOGO_DELIMITERS<span style="font-weight: bold">:
        </span>symbol <span style="font-weight: bold">+= </span>chars<span style="font-weight: bold">.</span>pop<span style="font-weight: bold">()
    </span><span style="color: blue; font-weight: bold">return </span>symbol

<span style="color: blue; font-weight: bold">def </span>parse_token<span style="font-weight: bold">(</span>chars<span style="font-weight: bold">):
    </span><span style="color: darkred">"""Parse the next token from a buffer chars, starting at chars.current."""
    </span>ch <span style="font-weight: bold">= </span>chars<span style="font-weight: bold">.</span>current
    <span style="color: blue; font-weight: bold">if </span>ch <span style="color: blue; font-weight: bold">in </span>LOGO_OPERATORS<span style="font-weight: bold">:
        </span><span style="color: blue; font-weight: bold">if </span>ch <span style="font-weight: bold">!= </span><span style="color: red">'-' </span><span style="color: blue; font-weight: bold">or </span>chars<span style="font-weight: bold">.</span>previous <span style="color: blue; font-weight: bold">not in </span><span style="font-weight: bold">[</span><span style="color: red">' '</span><span style="font-weight: bold">, </span><span style="color: blue">None</span><span style="font-weight: bold">]: </span><span style="color: green; font-style: italic"># Negative numbers
            </span><span style="color: blue; font-weight: bold">return </span>chars<span style="font-weight: bold">.</span>pop<span style="font-weight: bold">()
    </span><span style="color: blue; font-weight: bold">return </span>parse_symbol<span style="font-weight: bold">(</span>chars<span style="font-weight: bold">)

</span>
</pre>
</body>
</html>